Глава 15

Обработка ошибок

ColdFusion обладает достаточным набором инструментов и методов, позволяющих отлаживать и обрабатывать ситуации, которые приводят к ошибкам (исключительным ситуациям), и благодаря этим инструментам и методам можно предотвращать возможные ошибки и восстанавливать нормальную работу приложения после сбоев, которые в противном случае были бы фатальными.

Следует отметить, что главным инструментом при отладке CFML-страниц является непосредетвенно сам редактор ColdFusion Studio, работа с которым была описана в предыдущих главах книги. Впрочем, ColdFusion Server обладает некоторым набором инструментов, позволяющих отслеживать значения переменных, анализировать результаты выполнения запросов и отлаживать отдельные страницы.

Отладка приложения

Для отслеживания значения переменных можно использовать тег <CFDUMP>, позволяющий наглядно демонстрировать значения простых переменных, запросов, массивов, структур и WDDX-переменных, созданных с помощью тега <CFWDDX>.

Например, для отладки структуры AttribMyTable достаточно добавить следующую строку:

<CFDUMP var = #AttribMyTable#>

Для отладки запроса (query) можно также использовать тег <CFDUMP>, позволяющий выводить таблицу значений указанного запроса. Однако существует еще одна разновидность отладки запроса. Это добавление атрибута DEBUG. Например:

<CFQUERY NAME="GetTour" DATASOURCE="ttapplication.dsn#" DEBUG="Yes">

SELECT * FROM Tour </CFQUERY>

В результате внизу страницы будет выведена информация о количестве записей текущего запроса, времени выполнения и самом запросе, как показано ниже:

GetTour (Records=4, Time=10ms) SQL = SELECT * FROM Tour

Для отладки отдельного документа с возможностью просмотра сведений о времени выполнения (execution time), параметрах URL (URL parameters) и переменных окружения CGI (CGI variables) можно воспользоваться простым добавлением в конец строки URL определения следующего параметра mode=debug. При этом вся строка URL для документа MyPage.cfm может выглядеть так:

http://127.0.0.l/my-app/MyPage.cfm?mode=debug

Немаловажными для отладки документа подобным образом, так же, как и для предыдущего примера с добавлением к запросу атрибута DEBUG, являются настройки на странице администратора "ColdFusion Administrator". По умолчанию возможность просмотра отладочной информации предоставляется всем. Для ограничения же необходимо определить IP-адреса компьютеров, имеющих право для просмотра отладочной информации, используя при этом раздел страницы администратора Server | Debug Settings | Debugging IPs (Сервер | Параметры отладки | IP-адреса для отлаки), как показано на рис. 15.1.

Также можно настроить получаемую информацию, воспользовавшись разделом Server | Debug Settings | Debug Options (Сервер | Параметры отладки | Настройка отладки) все той же страницы администратора.

Рис. 15.1. Страница "ColdFusion Administrator", раздел Debugging IPs

Обработка ошибок

Методы, позволяющие обрабатывать ошибки, можно разделить на две категории:

<CFTRY>/<CFCATCH>, <CFTHROW>, <CFRETHROW>.

Тег <CFERROR>

Синтаксис:

<CFERROR TYPE = "Validation | Request | Monitor | Exception" TEMPLATE = "template_path" MAILTO = "email address" EXCEPTION = "exception_type">

В табл. 15.1 приведено описание атрибутов тега <CFERROR>.

Таблица 15.1. Описание атрибутов тега <CFERROR>

Атрибут

Описание

TYPE

TEMPLATE MAILTO EXCEPTION

Тип ошибки. Обязательный атрибут. Возможные значения:

  • Validation— происходит при неправильном вводе данных в форме;
  • Request — происходит при любых исключениях, которые иначе не обрабатываются. При этом шаблон сообщения об ошибках выполняется после исполнения CFML-страницы. Следует использовать в резервных целях;
    Monitor — происходит перед любыми другими обработками исключений, после чего обработка ошибок может продолжаться иными средствами, например с помощью тегов <CFTRY>/<CFCATCH>. Для данного типа можно определять любые возможные исключения. Используется для контроля и отладки исключений только на этапе проектирования приложения;
  • Exception— используется для определения исключительной ситуации. Можно определить различные шаблоны ошибок для разных типов исключений

Относительный путь к пользовательскому шаблону ошибок. Обязательный атрибут

Электронный адрес, по которому следует уведомлять о происходящих ошибках. Необязательный атрибут

Исключение. Обязательный атрибут при использовании таких типов ошибок, как Monitor и Exception

 

Типы исключительных ситуаций

Тип исключительной ситуации может быть учтен как при использовании атрибута EXCEPTION тега <CFERROR>, так и в сочетании с атрибутом TYPE тега <CFCATCH>, предназначенным для формирования конструкций обработки исключительных ситуаций, непосредственно на страницах приложения. Основные исключительные ситуации ColdFusion представлены в табл. 15.2.

Таблица 15.2. Типы исключительных ситуаций

Тип

Описание

Database

 

Template

Фиксирует неудачные действия с базами данных и проблемы, связанные с ODBC

Обнаруживает ошибки в работе с шаблонами. Подобные исключения могут генерироваться при использовании тегов

<CFINCLUDE>, <CFMODULE> И <CFERROR>

Тип

Описание

Missinglnclude

Обнаруживает ошибки, где встречаются ссылки на несуществующие файлы

Object

Обнаруживает ошибки в программном коде ColdFusion, который предусматривает работу с объектами

Security

Фиксирует ошибки в программном коде ColdFusion, который предусматривает обеспечение безопасности

Expression

Обнаруживает ошибки при неправильном использовании выражений

Lock

Фиксирует ошибки при неудачной блокировке или во время выполнения блокировок, организованных с помощью тега

<CFLOCK>

Application

Обнаруживает ошибки приложения, вызываемые тегом

<CFTHROW>

Any

ч Обнаруживает любые ошибки, которые не определены другими исключениями, в том числе неожиданные внутренние ошибки

Custom exception type

Обнаруживает пользовательские ошибки, вызываемые тегом

<CFTHROW>

 

Создание собственных шаблонов сообщений об ошибках

Для обнаружения большинства ошибок ColdFusion Server использует стандартную страницу. Впрочем, определяя собственные шаблоны в конфигурационном файле приложения Application.cfm, вы можете управлять выводимой информацией при возникновении ошибок различного характера. Причем ColdFusion позволяет определять шаблоны для различных типов исключительных ситуаций и обращаться с разными типами исключений различными способами.

Предположим, нам необходимо выводить сообщения об ошибках двух видов для ситуаций при некорректном заполнении форм (Validation) и для любых других ошибочных ситуаций, которые иначе не обрабатываются (Request). Решением данной задачи может быть следующий код, помещенный в конфигурационный файл Application.cfm приложения:

<CFERROR TYPE="Validation"

TEMPLATE="ErrorsTemplatel.cfm" MAILTO="Administrator@ipr.ru">

<CFERROR TYPE="Request"

TEMPKATE="ErrorsTemplate2.cfm" MAILTO="WebMaster@ipr.ru">

Здесь ErrorsTemplatel.cfm и ErrorsTemplate2.cfm являются шаблонами, определяющими содержание сообщений при возникновении исключительных ситуаций.

Для формирования непосредственно самих шаблонов сообщения об ошибках ColdFusion предоставляет целый набор встроенных переменных, определяющих ошибки. Причем в зависимости от типа ошибки могут быть активизированы разные переменные. Например, для типа ошибок validation поместим в наш шаблон ErrorsTemplatesl.cfm следующие переменные:

А для типа ошибок Request поместим в шаблон ErrorsTemplates2.cfm такие встроенные переменные:

Также можно использовать следующие встроенные переменные ошибок:

Далее продемонстрируем полный код страниц ErrorsTemplatel.cfm (листинг 15.1) и ErrorsTemplate2.cfm (листинг 15.2), позволяющих выводить сообщения в момент возникновения различных ошибок.

Листинг 15.1. Код страницы ErrorsTemplatel.cfm

<HTML> <HEAD>

<link rel="STYLESHEET" type="text/css" href="Style.css">

<TITLE>ErrorsTemplatel</TITLE> </HEAD> <BODY>

<hl>Errorl</hl> <TABLE border="0">

<TR><TD bgcolor="Black" class="txtErr">ValidationHeader</TD></TR>

<TR><TD bgcolor="Silver">IError. ValidationHeader#</TD></TR>

<TR><TD bgcolor="Black" class="txtErr">InvalidFields</TD></TR>

<TR><TD bgcolor="Silver">tError.InvalidFieldst</TD></TR>

<TR><TD bgcolor="Black" class="txtErr">ValidationFooter</TD></TR>

<TR><TD bgcolor="Silver">#Error.ValidationFooter#</TD></TR>

</TABLE> </BODY> </HTML>

Листинг 15.2. Код страницы ErrorsTemplate2.cfm

<HTML>

<HEAD>

<link rel="STYLESHEET" type="text/css" href="Style.css">

<TITLE>ErrorsTemplate2</TITLE>

</HEAD> <BODY>

<hl>Error2</hl>

<TABLE border="0"> <TR bgcolor="Black">

<TD class="txtErr">Template</td> <TD class="txtErr">DateTime</td>

</TR> <TR bgcolor="Silver">

<TD>#Error.Template#</td> <TD>#Error.DateTime#</td> </TR>

<TR><TD colspan="2" bgcolor="Black"

class="txtErr">Diagnostics</td></tr>

<TR><TD colspan="2" bgcolor="Silver" class="txtErr2">

# Error. Diagnosticsl</TD></TR>

<TR><TD colspan="2" bgcolor="Black"

class="txtErr">Browser</TDX/TR>

<TRXTD colspan="2" bgcolor="Silver">#Error.Browser#</TD></TR>

<TR bgcolor="Black">

<TD class="txtErr">RemoteAddress</td>

<TD class="txtErr">MailTo</td>

</TR> <TR bgcolor="Silver">

<TD>#Error. RemoteAddress#</TD> <TD>#Error.MailTot</TD> </TR>

</TABLE> </BODY> </HTML>

В дальнейшем остается лишь проверить работу созданных нами шаблонов. Например, создадим форму ввода, где при заполнении полей определенно будет сгенерирована ошибка с типом validation:

<HTML> <HEAD>

<TITLE>ErrorValidation</TITLE> </HEAD>

<BODY>

<FORM action="Action.cfm" method="Post">

<input type="Text" name="Field"><br>

<input type="Text" name="Field integer">

<input type="Hidden" name="Field_integer"

value="Error hidden field">

<input type="Submit" value="Send">

</FORM> </BODY> </HTML>

Приведем еще один пример, где в коде преднамеренно допустим ошибку типа Request, как показано ниже:

<CFIF isDeeffined("MyVal")> </CFIF>

Пользовательские шаблоны сообщений об ошибках позволяют только обогатить Web-приложения собственными стилизованными формами. Необходимо отметить, что ColdFusion Server автоматически регистрирует ошибки в log-файлах в следующих случаях:

В других случаях, при необходимости регистрировать ситуации, приводящие к ошибкам, необходимо создавать пользовательский log-файл и формировать код, позволяющий производить запись о возникающих ошибках.

Обработка исключительных ситуаций

Одно из главных преимуществ системы обработки исключительных ситуаций по сравнению с традиционными методами обработки ошибок состоит в отделении процедуры обнаружения ошибки от процедуры ее обработки. В ColdFusion для формирования конструкций обработки исключительных ситуаций непосредственно на страницах приложения необходимо использовать Теги <CFTRY>/<CFCATCH>.

Теги <CFTRY>/<CFCATCH>

<CFTRY>

Код с возможным исключением

<CFCATCH TYPE = "Exceptiontype">

Код обработки исключительной ситуации

</CFCATCH>

Дополнительный код для блока сfeatch </CFTRY>

Здесь атрибут TYPE может принимать одно из значений типа исключительной ситуации, описанных выше. Внутри же блока <CFTRY> содержится код, в ходе выполнения которого могут возникать исключения или аварийное завершение программы, соответствующим образом обрабатываемые посредством блока <CFCATCH> или путем переадресации исключения с использованием тега <CFTHROW>.

Например:

<HTML> <HEAD>

<TITLE>CFTRY example1</TITLE> </HEAD> <BODY> <CFTRY>

<CF_NumFormat Value = "10.123" Format = "__._">

<CFCATCH>

Error Message </CFCATCH> </CFTRY> </BODY> </HTML>

Здесь в коде программы между тегами <CFTRY> и <CFCATCH> преднамеренно допущена ошибка, а в блок <CFCATCH> помещен код обработки исключительной ситуации. В результате на экран будет выведено следующее сообщение сигнализирующее об ошибке:

Error Message

Отметим, что в приведенном примере блок <CFCATCH> использован без указания типа исключительной ситуации, что подразумевает обработку любых ошибок. Причем внутри блока <CFTRY> может следовать любое количество блоков <CFCATCH>. При отсутствии же хотя бы одного блока <CFCATCH>, что вполне допустимо, применение блока <CFTRY> бессмысленно.

Следующим примером разделим обработку исключений для разных типов, в частности предусмотрим исключение, фиксирующее неудачные действия по отношению к базам данных (Database), при неправильном использовании выражений (Expression) и для остальных ошибок (Anу):

<HTML> <HEAD>

<TITLE>CFTRY example2</TITLE> </HEAD>

<BODY>

<CFTRY>

<CFQUERY NAME="GetTour" DATASOURCE="#application.dsn#">

SELECT * FROM Tour </CFQUERY>

<CF_NumFormat Value = "10.123" Format = "__._e">

<CFCATCH TYPE="Database">

<CFOUTPUT>Error Code: #Cfcatch.ErrorCode#</3FOUTPUT><br>

<CFOUTPUT>Detail: #Cfcatch.Detail#</CFOUTPUT> </CFCATCH>

<CFCATCH TYPE="Expression">

Expression Error </CFCATCH> <CFCATCH TYPE="Any">

Any Error </CFCATCH> </CFTRY>

</BODY> </HTML>

Все исключения обрабатываются последовательно в зависимости от расстановки блоков <CFCATCH>. В нашем примере, если проблем с базой данных не будет, то программа перейдет к обработке ошибок, возникших при использовании неправильных выражений. Если и здесь проблем не будет, то следующим шагом станут обрабатываться все остальные возможные исключения. Причем в нашем случае при возникновении исключения с типом Database на экран будет выведен код и детальная информация об ошибке, определяемые с помощью внутренних переменных захвата Cf catch. ErrorCode и Cf catch. Detail. Например, cледующий результат может указывать на невозможность соединения с базой данных:

Error Code: 08001

Detail: [Sybase][ODBC Driver][Adaptive Server Anywhere]

Unable to connect to database server:

Database server not running

Приложение ColdFusion позволяет объявлять собственные исключительные ситуации и производить переадресацию исключений с использованием тега <CFTHROW>.

Тег <CFTHROW>

Синтаксис:

<CFTHROW TYPE = "exception_type" MESSAGE V "message"

DETAIL = "detail_description"

ERRORCODE = "error_code" EXTENDEDINFO = "additional_information">

В табл. 15.3 представлено описание атрибутов тега <CFTHROW>.

Таблица 15.3. Описание атрибутов тега <CFTHROW>

Атрибут

Описание

TYPE

MESSAGE

DETAIL ERRORCODE EXTENDEDINFO

Пользовательский тип исключения. Необязательный атрибут. Если данный тип не определен, то с помощью тега <CFCATCH> необходимо определить захват типа Application или Any, куда будет перенаправлено данное исключение

Сообщение, которое описывает исключительную ситуацию. Необязательный атрибут

Детальное описание исключения. Необязательный атрибут Пользовательский код ошибки. Необязательный атрибут Дополнительное описание исключения. Необязательный атрибут

Например, следующий код позволяет генерировать пользовательское исключение муЕхр по воскресеньям:

<HTML> <HEAD>

<TITLE>CFTRY example3</TITLE>

</HEAD> <BODY> <CFTRY>

<CFSET NowDayWeek = DayOfWeek(Now () ) >

<CFIF Variables.NowDayWeek eq 1>

<CFTHROW TYPE="MyExp" ERRORCODE="1" EXTENDEDINFO="NotSundays"

DETAIL="Today Sunday, that obliges you well to have a rest!" MESSAGE = "I do not work on Sundays."> </CFIF> <CFCATCH TYPE="MyExp">

Message: <CFOUTPUT>ttCfcatch.Message#</CFOUTPUT> </CFCATCH>

<CFCATCH TYPE="Any">

Any Error </CFCATCH> </CFTRY>

</BODY> </HTML>

И если предположить, что данный код выполнится в первый день недели, то на экран будет выведено сообщение об ошибке с помощью внутренней переменной захвата Сfcatch.Message, как показано ниже:

Message: I do not work on Sundays.

Если вам необходимо выполнить некоторые действия при возникновении исключения во внутреннем блоке <CFTRY>, но не прекратить на этом обработку, а передать исключение дальше, внешнему обработчику, вы можете воспользоваться тегом <CFRETHROW>, позволяющим регенерировать исключение. Например:

<HTML> <HEAD>

<TITLE>CFTRY example4</TITLE> </HEAD> <BODY> <CFTRY>

<CFTRY> <CF_NumFormat Value = "10.123" Format = "__-_e">

<CFCATCH TYPE="Expression">

ErrNumber: <CFOUT.PUT>#Cfcatch. ErrNumber#</CFOOTPUT><br>

<CFRETHROW>

</CFCATCH> </CFTRY>

<CFOUTPUT>MyCode</CFOUTPUT> <CFCATCH TYPE="Any">

Type: <CFOUTPUT>#Cfcatch.Type#</CFOUTPUT> </CFCATCH> </CFTRY>

</BODY> </HTML>

В результате выполнения приведенного примера будет выведен номер ошибки и тип исключения, .определяемые с помощью внутренних переменных захвата cfcatch.ErrNumber и cfcatch.Type, как показано ниже:

ErrNumber: 16399 Type: EXPRESSION

Чтобы подвести итог в описании исключительных ситуаций, приведем список внутренних переменных захвата, часть из которых уже была использована в представленных примерах.

Внутренние переменные захвата для большинства типов исключений: П Cf catch. Type — тип исключения;

Переменные захвата для исключения Database:

Переменная захвата для исключения Expression: Cfcatch.ErrNumber — номер ошибки выражения.

Переменные захвата для исключения Lock:

Cf catch. MissingFileName — имя отсутствующего файла.

Резюме

Подведем итог. В данной главе вы познакомились с CFML-тегами <CFERROR>, <CFTRY>/<CFCATCH>, <CFTHROW>, <CFRETHROW>.